#!groovy

node {
  def rootPath = "/src/rancher-validation/"
  def containerPrefix = "${JOB_NAME}${BUILD_NUMBER}"

  def rancherConfig = "rancher_env.config"
  def imageName = "rancher-validation-${JOB_NAME}${env.BUILD_NUMBER}"
  def testsDir = "tests/v3_api/"

  def pre_branch = PREUPGRADE_BRANCH
  def post_branch = POSTUPGRADE_BRANCH

  def buildFail = false

  wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm', 'defaultFg': 2, 'defaultBg':1]) {
    withCredentials([ string(credentialsId: 'AWS_ACCESS_KEY_ID', variable: 'AWS_ACCESS_KEY_ID'),
                      string(credentialsId: 'AWS_SECRET_ACCESS_KEY', variable: 'AWS_SECRET_ACCESS_KEY'),
                      string(credentialsId: 'AWS_ACCESS_KEY_ID', variable: 'RANCHER_EKS_ACCESS_KEY'),
                      string(credentialsId: 'AWS_SECRET_ACCESS_KEY', variable: 'RANCHER_EKS_SECRET_KEY'),
                      string(credentialsId: 'DO_ACCESSKEY', variable: 'DO_ACCESSKEY'),
                      string(credentialsId: 'AWS_SSH_PEM_KEY', variable: 'AWS_SSH_PEM_KEY'),
                      string(credentialsId: 'RANCHER_SSH_KEY', variable: 'RANCHER_SSH_KEY'),
                      string(credentialsId: 'AZURE_SUBSCRIPTION_ID', variable: 'AZURE_SUBSCRIPTION_ID'),
                      string(credentialsId: 'AZURE_TENANT_ID', variable: 'AZURE_TENANT_ID'), 
                      string(credentialsId: 'AZURE_CLIENT_ID', variable: 'AZURE_CLIENT_ID'),
                      string(credentialsId: 'AZURE_CLIENT_SECRET', variable: 'AZURE_CLIENT_SECRET'),
                      string(credentialsId: 'AZURE_SUBSCRIPTION_ID', variable: 'RANCHER_AKS_SUBSCRIPTION_ID'),
                      string(credentialsId: 'AZURE_TENANT_ID', variable: 'RANCHER_AKS_TENANT_ID'), 
                      string(credentialsId: 'AZURE_CLIENT_ID', variable: 'RANCHER_AKS_CLIENT_ID'),
                      string(credentialsId: 'AZURE_CLIENT_SECRET', variable: 'RANCHER_AKS_SECRET_KEY'),
                      string(credentialsId: 'RANCHER_REGISTRY_USER_NAME', variable: 'RANCHER_REGISTRY_USER_NAME'),
                      string(credentialsId: 'RANCHER_REGISTRY_PASSWORD', variable: 'RANCHER_REGISTRY_PASSWORD'),
                      string(credentialsId: 'ADMIN_PASSWORD', variable: 'ADMIN_PASSWORD'),
                      string(credentialsId: 'USER_PASSWORD', variable: 'USER_PASSWORD'),
                      string(credentialsId: 'RANCHER_GKE_CREDENTIAL', variable: 'RANCHER_GKE_CREDENTIAL')]) {
      stage('Prechecks & checkout preupgrade branch') {
        if (RANCHER_SERVER_VERSION == "") {
          currentBuild.result = 'ABORTED'
          error("RANCHER_SERVER_VERSION must be provided!")
        }

        if (RANCHER_SERVER_VERSION_UPGRADE == "") {
          currentBuild.result = 'ABORTED'
          error("RANCHER_SERVER_VERSION_UPGRADE must be provided!")
        }

        if (PREUPGRADE_BRANCH == "") {
          currentBuild.result = 'ABORTED'
          error("PREUPGRADE_BRANCH must be provided!")
        }

        if (POSTUPGRADE_BRANCH == "") {
          currentBuild.result = 'ABORTED'
          error("POSTUPGRADE_BRANCH must be provided!")
        }

        deleteDir()
        checkout([
                  $class: 'GitSCM',
                  branches: [[name: "*/${pre_branch}"]],
                  extensions: scm.extensions + [[$class: 'CleanCheckout']],
                  userRemoteConfigs: scm.userRemoteConfigs
                ])
        
        if (RANCHER_EXTRA_VARS != "" && RANCHER_EXTRA_VARS != null) {
          echo "${RANCHER_EXTRA_VARS}"
          writeFile(file: "preenv.config", text: "${RANCHER_EXTRA_VARS}")
          load "preenv.config"
        } 
      }

      stage('Configure and Build') {
        if (env.AWS_SSH_PEM_KEY && env.AWS_SSH_KEY_NAME) {
          dir("./tests/validation/.ssh") {
            def decoded = new String(AWS_SSH_PEM_KEY.decodeBase64())
            writeFile file: AWS_SSH_KEY_NAME, text: decoded
          }
        }
        sh "./tests/validation/tests/v3_api/scripts/configure.sh"
        sh "./tests/validation/tests/v3_api/scripts/build.sh"
      }

      stage('Deploy Rancher server') {
        try {
          sh "docker run --name ${containerPrefix}_deploy -t --env-file .env " +
              "${imageName} /bin/bash -c \'" +
              "pytest -v -s --junit-xml=deploy.xml " +
              "-k test_deploy_rancher_server ${testsDir}\'"

              sh "docker cp ${containerPrefix}_deploy:${rootPath}${testsDir}${rancherConfig} ."
              load rancherConfig
        } catch(err) {
          buildFail = true
          echo "Error: " + err
          echo "Deploy Rancher server failed"
          currentBuild.result = 'FAILURE'
        }
      }

      stage('Provision cluster') {
        try {
          sh "docker run --name ${containerPrefix}_provision  --env-file .env " +
            "${imageName} /bin/bash -c \'" +
            "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " +
            "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
            "export USER_TOKEN=${USER_TOKEN} && " +
            "pytest -v -s --junit-xml=provision.xml -k test_rke_${RANCHER_CLUSTER_TYPE}_host_${RANCHER_CLUSTER_PROFILE} ${testsDir}\'"
        } catch(err) {
          buildFail = true
          echo "Error: " + err
          echo "Provision cluster failed."
          currentBuild.result = 'FAILURE'
        }
      }

      stage('Run preupgrade') {
        try {
          sh "docker run --name ${containerPrefix}_preupgrade  --env-file .env " +
            "${imageName} /bin/bash -c \'" +
            "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
            "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
            "export USER_TOKEN=${USER_TOKEN} && " +
            "export RANCHER_VALIDATE_RESOURCES_PREFIX=autopre && " +
            "export RANCHER_CREATE_RESOURCES_PREFIX=autopre && " +
            "export RANCHER_UPGRADE_CHECK=preupgrade && " +
            "export RANCHER_INGRESS_CHECK=True && " +
            "export RANCHER_ENABLE_HOST_NODE_PORT_TESTS=True && " +
            "export RANCHER_SKIP_INGRESS=False && " +
            "export RANCHER_CHECK_FOR_LB=False && " +
            "pytest -v -s --junit-xml=preupgrade.xml -k test_upgrade ${testsDir}\'"
        } catch(err) {
          buildFail = true
          echo "Error: " + err
          echo "Preupgrade tests failed"
          currentBuild.result = 'UNSTABLE'
        }
      }
      
      stage('Checkout postupgrade branch & rebuild') {
        checkout([
                  $class: 'GitSCM',
                  branches: [[name: "*/${post_branch}"]],
                  extensions: scm.extensions,
                  userRemoteConfigs: scm.userRemoteConfigs
                ])

          if (env.AWS_SSH_PEM_KEY && env.AWS_SSH_KEY_NAME) {
            dir("./tests/validation/.ssh") {
              def decoded = new String(AWS_SSH_PEM_KEY.decodeBase64())
              writeFile file: AWS_SSH_KEY_NAME, text: decoded
            }
          }

          sh "./tests/validation/tests/v3_api/scripts/configure.sh"
          sh "./tests/validation/tests/v3_api/scripts/build.sh"
      }

      stage('Run upgrade') {
        try {
          sh "docker run --name ${containerPrefix}_upgrade  --env-file .env " +
            "${imageName} /bin/bash -c \'" +
            "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
            "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
            "export USER_TOKEN=${USER_TOKEN} && " +
            "export RANCHER_UPGRADE_CHECK=upgrade_rancher && " +
            "pytest -v -s --junit-xml=upgrade.xml -k test_rancher_upgrade ${testsDir}\'"
        } catch(err) {
          buildFail = true
          echo "Error: " + err
          echo "Upgrade Rancher failed."
          currentBuild.result = 'FAILURE'
        }
      }

      stage('Run postupgrade tests') {
        try {
          sleep(time: 5, unit: "MINUTES")
          sh "docker run --name ${containerPrefix}_postupgrade  --env-file .env " + \
            "${imageName} /bin/bash -c \'" + 
            "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
            "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
            "export USER_TOKEN=${USER_TOKEN} && " +
            "export RANCHER_VALIDATE_RESOURCES_PREFIX=autopre && " +
            "export RANCHER_CREATE_RESOURCES_PREFIX=autopost && " +
            "export RANCHER_UPGRADE_CHECK=postupgrade && " +
            "export RANCHER_INGRESS_CHECK=True && " +
            "export RANCHER_ENABLE_HOST_NODE_PORT_TESTS=True && " +
            "export RANCHER_SKIP_INGRESS=False && " +
            "export RANCHER_CHECK_FOR_LB=False && " +
            "pytest -v -s --junit-xml=postupgrade.xml -k test_upgrade ${testsDir}\'"
        } catch(err) {
          buildFail = true
          currentBuild.result = 'UNSTABLE'
          echo "Error: " + err
          echo "Postupgrade tests failed"
        }
      }  

      stage('Upgrade k8s') {
        try {
          if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
            sh "docker run --name ${containerPrefix}_k8supgrade  --env-file .env " +
              "${imageName} /bin/bash -c \'" +
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
              "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
              "export USER_TOKEN=${USER_TOKEN} && " +
              "pytest -v -s --junit-xml=k8supgrade.xml -k test_edit_cluster_k8s_version ${testsDir}\'"
          }
        } catch(err) {
          buildFail = true
          echo "Error: " + err
          echo "Upgrade cluster k8s failed."
          currentBuild.result = 'FAILURE'
        }
      }

      stage('Run postupgrade scripts') {
        try {
          if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
            sh "docker run --name ${containerPrefix}_k8spostupgrade  --env-file .env " +
              "${imageName} /bin/bash -c \'" + 
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
              "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
              "export USER_TOKEN=${USER_TOKEN} && " +
              "export RANCHER_VALIDATE_RESOURCES_PREFIX=autopost && " +
              "export RANCHER_CREATE_RESOURCES_PREFIX=autopost2 && " +
              "export RANCHER_UPGRADE_CHECK=postupgrade && " +
              "export RANCHER_INGRESS_CHECK=True && " +
              "export RANCHER_ENABLE_HOST_NODE_PORT_TESTS=True && " +
              "export RANCHER_SKIP_INGRESS=False && " +
              "export RANCHER_CHECK_FOR_LB=False && " +
              "pytest -v -s --junit-xml=k8spostupgrade.xml -k test_upgrade ${testsDir}\'"
          }
        } catch(err) {
          buildFail = true
          echo "Error: " + err
          echo "k8s postupgrade scripts failed"
          currentBuild.result = 'UNSTABLE'
        }
      }

      stage('Delete Rancher Server') {
        try {
          if (RANCHER_DELETE_SERVER.toLowerCase() == "true" && buildFail == false) {
            sh "docker run --name ${containerPrefix}_delete -t --env-file .env " + 
            "${imageName} /bin/bash -c \'" +
            "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
            "export USER_TOKEN=${USER_TOKEN} && " +
            "pytest -v -s --junit-xml=delete.xml " +
            "-k test_delete_rancher_server ${testsDir}\'"
          } else {
            echo "Build failed or RANCHER_DELETE_SERVER is set to false"
            echo "SERVER IS NOT DELETED"
          }
        } catch(err) {
          echo "Error: " + err
          error()
          currentBuild.result = 'FAILURE'
        }
      }

      stage('Test Reports') {
        try {
          sh "docker cp ${containerPrefix}_deploy:${rootPath}deploy.xml ."
          sh "docker cp ${containerPrefix}_provision:${rootPath}provision.xml ."
          sh "docker cp ${containerPrefix}_preupgrade:${rootPath}preupgrade.xml ."
          sh "docker cp ${containerPrefix}_upgrade:${rootPath}upgrade.xml ."
          sh "docker cp ${containerPrefix}_postupgrade:${rootPath}postupgrade.xml ."
          
          if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
            sh "docker cp ${containerPrefix}_k8supgrade:${rootPath}k8supgrade.xml ."
            sh "docker cp ${containerPrefix}_k8spostupgrade:${rootPath}k8spostupgrade.xml ."  
          }
          
          if (RANCHER_DELETE_SERVER.toLowerCase() == "true" && buildFail == false) {
            sh "docker cp ${containerPrefix}_delete:${rootPath}delete.xml ."
          }
          
          step([$class: 'JUnitResultArchiver', testResults: "**/*.xml"])
        } catch(err) {
          echo "Error: " + err
        }
      }

      stage('Cleanup') {
        sh "docker rm ${containerPrefix}_deploy"
        sh "docker rm ${containerPrefix}_provision"
        sh "docker rm ${containerPrefix}_preupgrade"
        sh "docker rm ${containerPrefix}_upgrade"
        sh "docker rm ${containerPrefix}_postupgrade"

        if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
          sh "docker rm ${containerPrefix}_k8supgrade"
          sh "docker rm ${containerPrefix}_k8spostupgrade"
        }

        if (RANCHER_DELETE_SERVER.toLowerCase() == "true" && buildFail == false) {
          sh "docker rm  ${containerPrefix}_delete"
        }

        sh "docker rmi ${imageName}"
      }
    }
  }
}